#ifndef TOOLS_H
#define TOOLS_H

#include "main.h"

namespace tls {
	size_t memoryAvailable();

	// return a est une puissance de 2
	bool is2Pwr(int a);



	/**
	 * return rightmost zerobit
	 * if nb is all one,
	 * recherche dichotomique
	 */
	template<typename T>
	ui8 bitSearchOptimized(T &nb) {

		uint32_t maskgen = ~0;
		uint8_t maskRightMove = 8 * sizeof(T);
		uint8_t maskLeftMove = 0;

		do {
			if (!(~nb & (maskgen << maskLeftMove)))
				maskLeftMove += maskRightMove;
			maskgen >>= maskRightMove /= 2;
		} while (maskRightMove);

		return maskLeftMove;
	}

	/**
	 * recherche du right-most-zero bit
	 */
	template<typename T>
	ui8 bitSearchLinear(T &nb) {
		ui8 bit = 0;
		T rightMostBit = (T) 1;
		while (nb & (rightMostBit << bit))
			bit++;
		return bit;
	}

	/**
	 * Affiche les digits binaires du parametre.
	 */
	template<typename TUI>
	void printbit(TUI i) {
		std::cout << 8 * sizeof(TUI) << "b : ";
		TUI mask = 1;
		for (size_t bit = 8 * sizeof(TUI) - 1; bit + 1 > 0; --bit) {
			std::cout << ((i & (mask << bit)) != 0);
			if (!(bit % 8))
				std::cout << " ";
		}
		std::cout << std::endl;
	}

	template<typename tui>
	constexpr tui RightMostBit() {
		return tui(1);
	}

	template<typename tui>
	constexpr tui LeftMostBit() {
		return tui(1) << (sizeof(tui) * 8 - 1);
	}

	template<typename tui>
	constexpr tui AllOneBit() {
		return tui(~0);
	}

	template<typename tui>
	constexpr tui AllZeroBit() {
		return tui(0);
	}

	template<typename T> inline
	void ClrBit(T &area, T mask) {
		area &= ~mask;
	}

	template<typename T> inline
	void SetBit(T &area, T mask) {
		area |= mask;
	}

	template<typename T> inline
	void TglBit(T &area, T mask) {
		area ^= mask;
	}


//template<typename tui>
//constexpr tui allOne = tui(~0);
}

#endif // TOOLS_H
